<!DOCTYPE html>
<html lang="en" translate="no">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
    <title>Document</title>
  </head>

  <body>
    <style>
      .container {
        width: 800px;
        height: 800px;
        padding: 10px;
        /* background-color: red; */
        display: grid;
        place-content: center;
        place-items: center;
        aspect-ratio: 1/1;
        scroll-behavior: smooth;
      }

      .box {
        width: 200px;
        height: 200px;
        background: skyblue;
        user-select: none;
      }
    </style>
    <h1 class="animate__animated animate__fadeInLeftBig">An animated element</h1>
    <div class="container">
      <div class="box"></div>
    </div>
    <button class="btn">按钮</button>

    <script type="module" defer>
      document.body.addEventListener('pageshow', myFunction);

      function myFunction(event) {
        // alert('该页面是否从浏览器缓存中读取? ' + event.persisted);
        console.log('该页面是否从浏览器缓存中读取? ' + event.persisted);
      }
      // 重排，回流是指改变页面的结构 比如 width left Dom操作 布局操作等 会让浏览器重新排布
      // 重绘是指改变页面的样式 比如 background 字体颜色
      // Reflect是ES6为了操作对象而新增的API, Proxy是对对象进行代理操作, Reflect一般情况下都会相互配合使用
      // console.log(Reflect.__proto__ === Object.prototype);
      // console.log(window.Reflect);
      // console.log(window.Proxy);

      // 动态css变量 var(--animate-duration)
      document.querySelector('body > h1').style.setProperty('--animate-duration', '3s');

      // document.documentElement.style.setProperty('--animate-duration', '2s');
      const obj = {
        name: '浏览器',
        age: 20,
        id: 15,
      };

      let reslut = Reflect.get(obj, 'name'); //获取属性
      Reflect.set(obj, 'desc', '这是谷歌'); //设置属性,返回值是一个Boolean的值。

      // Reflect.defineProperty方法类似的，不过唯一的区别是该方法与Object.defineProperty方法类似的，不过唯一的区别是 Reflect.defineProperty返回值是一个Boolean的值。
      // Reflect.has(target,name) 是否含有该对象的属性 会在原型上找 跟es5中的 in方法一样
      // Reflect.ownKeys(obj) 获取所有属性 包括symbol
      Reflect.deleteProperty(obj, 'name'); //删除属性
      // console.log(obj);
      // console.log(Reflect);

      // script标签中写js代码，或者使用src引入js文件时，默认不能使用module形式，即不能使用import导入文件，但是我们可以再script标签上加上type=module属性来改变方式。
      // 方法 1 ： 引入module.js，然后在script标签里面调用

      // cookie的使用:  可以用js-cookie插件 expires过期时间,path路径
      document.cookie = 'username=John Doe';
      document.cookie = 'username=John Smith; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/';
      // console.log(document.cookie);
      // 删除 cookie 非常简单。您只需要设置 expires 参数为以前的时间即可，如下所示，设置为 Thu, 01 Jan 1970 00:00:00 GMT:

      // Object.getOwnPropertySymbols(); //获取对象的Symbols属性

      // 封装获取cookie
      function getCookie(cname) {
        let name = cname + '=';
        ca = document.cookie.split(';');
        for (let i = 0; i < ca.length; i++) {
          let c = ca[i].trim();
          if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
        }
        return '';
      } // 匹配汉字
      // console.log(getCookie("username"));

      // for (let i = 0; i < 5; i++) {
      //   setTimeout(function() {
      //     console.log(i);
      //   });
      //   console.log(i);
      // }

      // for (let i = 0; i < 5; i++) {
      //   console.log(i);
      // }
      // console.log(i);

      // vue3 + vite + ts + elementPlus + 高德地图Api

      // Object.freeze(); //冻结
      // Object.getOwnPropertyDescriptor(); //属性的描述 w重写 c删除 e枚举

      // const date = new Date().getTime();
      // console.dir(date);
      // console.dir(Math);
      // console.log(Object.prototype.toString.call("a").slice(8, -1)); String Number

      //  XSS攻击:跨站脚本攻击)是一种代码注入攻击
      //  反之方式:对字符串进行编码。   encodeURIComponent()

      // 服务器告诉浏览器的格式:  Content-Type：text/HTML。
      // 浏览器告诉服务器格式: application/x- 开头。

      // application/x-www-form-urlencoded 这应该是默认的 POST 提交数据的方式了。浏览器的原生 form 表单
      // Content-Type 被指定为 application/x-www-form-urlencoded；其次，提交的数据按照 key1=val1&key2=val2 的方式进行编码
      // qs.stringify k库可以转换
      // Content-Type： multipart/form-data 一般用于二进制的上传 图片 视频 音频

      // application/json axios默认的get形式
      // text/xml

      // text/html ： HTML格式
      // text/plain ：纯文本格式
      // text/xml ： XML格式
      // image/gif ：gif图片格式
      // image/jpeg ：jpg图片格式
      // image/png：png图片格式

      // 以application开头的媒体格式类型：
      // application/xhtml+xml ：XHTML格式
      // application/xml： XML数据格式
      // application/atom+xml ：Atom XML聚合格式
      // application/json： JSON数据格式
      // application/pdf：pdf格式
      // application/msword ： Word文档格式
      // application/octet-stream ： 二进制流数据（如常见的文件下载）
      // application/x-www-form-urlencoded ： <form encType=””>中默认的encType，form表单数据被编码为key=value格式发送到服务器（表单默认的提交数据的格式）
      // multipart/form-data ： 需要在表单中进行文件上传时，就需要使用该格式需要配合formdata对象

      // 全局的 axios 默认值
      // axios.defaults.baseURL = 'https://api.example.com';
      // axios.defaults.headers.common['Authorization'] = token;
      // axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

      /**
       * @description: 正则表达
       * @param {*}
       * @return {*}
       */

      // let hd = 'houdunren2200hdcms998';
      // console.log(/\d/g.test(hd));
      // console.log(/\w/g.exec(hd));
      // console.log(hd.match(/\d/g));
      // console.log(hd.match(/\d/g).join(''));

      // let str = 'hn.com';
      // console.log(str.search("om"));

      // *	重复零次或更多次
      // +	重复一次或更多次
      // ?	重复零次或一次
      // {n}	重复n次
      // {n,}	重复n次或更多次
      // {n,m}	重复n到m次包括n m

      // | 表示左右任意一边2选1   ()表示一个组
      //  \d数字0-9 , \w与任意一个英文字母,数字或下划线匹配 \s空格 .点是匹配任意
      // 可以使用 [\s\S]+ 或 [\d\D] .* 来匹配所有字符

      //       []	只匹配其中的一个原子 ()表示一个组  // RegExp.$1
      // [^]	只匹配"除了"其中字符的任意一个原子
      // [0-9]	匹配0-9任何一个数字
      // [a-z]	匹配小写a-z任何一个字母
      // [A-Z]	匹配大写A-Z任何一个字母
      //通用的邮箱验证
      const regMail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/;

      // const proxy = new Proxy(
      //   {
      //     name: 'll',
      //   },
      //   {
      //     get(obj, property) {},
      //     set(obj, property, newValue) {
      //       // console.log("2");
      //     },
      //     // 删除
      //     deleteProperty(obj, property) {
      //       // console.log("删除");
      //     },
      //   }
      // );
      // proxy.age = 20;
      // delete proxy.name;
      // set 会自动吧字符串转成不能重复的伪数组
      // console.log([...new Set("houdunren")].join("")); //houdnre
      // console.log(new Set("houdunren")); //houdnre

      // console.log(new Set(["a", "b", "c", "d", "e", "f"]));

      // 对于键是对象的Map， 键保存的是内存地址，值相同但内存地址不同的视为两个键,但是WeaMap对键名是弱引用的，键值是正常引用。

      // ondragstart - 用户开始拖动元素时触发
      // ondrag - 元素正在拖动时触发
      // ondragend - 用户完成元素拖动后触发

      // ondragenter - 当被鼠标拖动的对象进入其容器范围内时触发此事件
      // ondragleave - 当被鼠标拖动的对象离开其容器范围内时触发此事件
      // ondragover - 当被鼠标拖动的对象在另一对象容器范围内移动时触发此事件
      // ondrop - 在一个拖动过程中，释放鼠标键时触发此事件

      // 将显示方式设置为表格，display:table-cell,同时设置vertial-align：middle'

      let arr = [3, 1, 4, 6, 5, 7, 2];
      function quickSort(arr) {
        if (arr.length === 0) {
          return []; // 返回空数组
        }
        let cIndex = Math.floor(arr.length / 2);
        let c = arr.splice(cIndex, 1);
        let l = [];
        let r = [];
        for (let i = 0; i < arr.length; i++) {
          if (arr[i] < c) {
            l.push(arr[i]);
          } else {
            r.push(arr[i]);
          }
        }
        return quickSort(l).concat(c, quickSort(r));
      }
      // console.log(arr);

      // Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。
      // Element.getBoundingClientRect().top：元素上边到视窗上边的距离
      // Element.getBoundingClientRect().right：元素右边到视窗左边的距离
      // Element.getBoundingClientRect().bottom：元素下边到视窗上边的距离
      // Element.getBoundingClientRect().left：元素左边到视窗左边的距离
      // Element.getBoundingClientRect().width：元素宽度 (不包括边框和内边距)
      // Element.getBoundingClientRect().height：元素高度
      // Element.getBoundingClientRect().x：用于left
      // Element.getBoundingClientRect().y：用于top

      // 学习别人的博客网站 https://www.crazyming.com/

      /*项目生成结构树*/
      //  sudo npm i tree-node-cli -g
      // 查看所有指令：
      // tree --help
      // 进入项目根目录，我们需要在README.md文件中写入目录，执行：
      // tree -L 4 -I "node_modules" > README.md
      // 其中参数-L 是确定要几级目录，-I是排除哪个文件夹下的
      // 如果生成的结构是乱的，可以用 代码块三点语法 包起来
      //

      // for (let i = 0; i < 5; i++) {
      //   setTimeout(function() {
      //     // console.log(i);
      //   }, 1000);
      // }

      function view() {
        let i = 0;
        (function handle() {
          if (i++ < 100) {
            setTimeout(handle, 1000);
            console.log(i);
          }
        })();
      }

      // let count = 0;
      // let num = 987654321;
      // function hd1() {
      //   for (let i = 0; i < 100000000; i++) {
      //     if (num <= 0) break;
      //     count += num--;
      //   }
      //   if (num > 0) {
      //     console.log(num);
      //     setTimeout(hd1);
      //   }
      // }
      // hd1();
      // console.log('houdunren.com'); //立刻显示出来
      // const div = document.getElementById('hd');
      // function handle() {
      //   let i = 0;
      //   (function run() {
      //     console.log(i);
      //     div.innerHTML = i;
      //     div.style.width = i + '%';
      //     if (++i <= 100) setTimeout(run, 10);
      //   })();
      // }
      // // handle()

      // async function load() {
      //   for (let i = 0; i <= 100; i++) {
      //     await new Promise((resolve) => {
      //       setTimeout(() => {
      //         resolve();
      //       }, 100);
      //     });
      //     div.innerHTML = i;
      //     div.style.width = i + '%';
      //   }
      // }
      // load();
      // view();

      //迭代器
      let iteratorObj = {
        name: 'llq',
        age: 20,
        desc: 'shuaige',
        arr: [11, 22, 33, 44],
        [Symbol.iterator]: function () {
          let index = 0;
          return {
            next: () => {
              if (index < this.arr.length) {
                let res = {
                  value: this.arr[index],
                  done: false,
                };
                index++;
                return res;
              } else {
                return {
                  value: undefined,
                  done: true,
                };
              }
            },
          };
        },
      };
      // for (item of iteratorObj) {
      //   console.log(item);
      // }

      function formatTime(time, option) {
        time = +time * 1000;
        const d = new Date(time);
        const now = Date.now();

        const diff = (now - d) / 1000;

        if (diff < 30) {
          return '刚刚';
        } else if (diff < 3600) {
          // less 1 hour
          return Math.ceil(diff / 60) + '分钟前';
        } else if (diff < 3600 * 24) {
          return Math.ceil(diff / 3600) + '小时前';
        } else if (diff < 3600 * 24 * 2) {
          return '1天前';
        }
        if (option) {
          return parseTime(time, option);
        } else {
          return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分';
        }
      }

      function parseTime(time, cFormat) {
        if (arguments.length === 0) {
          return null;
        }
        const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}';
        let date;
        if (typeof time === 'object') {
          date = time;
        } else {
          if (('' + time).length === 10) time = parseInt(time) * 1000;
          date = new Date(time);
        }
        const formatObj = {
          y: date.getFullYear(),
          m: date.getMonth() + 1,
          d: date.getDate(),
          h: date.getHours(),
          i: date.getMinutes(),
          s: date.getSeconds(),
          a: date.getDay(),
        };
        const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
          let value = formatObj[key];
          if (key === 'a') {
            return ['一', '二', '三', '四', '五', '六', '日'][value - 1];
          }
          if (result.length > 0 && value < 10) {
            value = '0' + value;
          }
          return value || 0;
        });
        return timeStr;
      }

      // keycode=123  是f12键
      // 禁止右键菜单
      document.oncontextmenu = function () {
        return false;
      };
      // 禁止文字选择
      document.onselectstart = function () {
        return false;
      };
      // 禁止复制
      document.oncopy = function () {
        return false;
      };
      // 禁止剪切
      document.oncut = function () {
        return false;
      };
      // 禁止粘贴
      document.onpaste = function () {
        return false;
      };

      // ['1','2','3'].map(parseInt) =>[1,NaN,NaN]
      // 0.1+0.2=0.3000000000004 他们转化成二进制是无限循环！ IEEE754标准 64位双精度表示（符号位 0正数 1负数，指数为，有效位，）
      // Nbumber.parseInt() 接受两个参数，第二个是标识是什么进制的数，必须在（2-36）之间， 0表示10进制 2表示2进制 1会返回NaN   number最大16位

      //  == 进行比较时，如果两边数据类型不一样，先转化成相同护具类型。规则如下：
      // 1.{} =={}  两个对象（obj，fun，arr，date，reg）比较时，比较的是堆内存的地址，栈指向堆内存地址
      // 2. null == undefined成立/ null===undefined不成立   null,undefined不成立与其他类型比较时都不相等
      // 3. NaN==NaN不成立 NaN和谁都不相等
      // 4.对象与字符串比较时，调用对象原型的toString()方法转成字符串在进行比较
      //5.  剩余情况比较时，都是转成数字进行比较（前提是数据类型不一样）

      // 滚动条到底部的条件即为：scrollTop + clientHeight === scrollHeight

      // let log = console.log.bind(document);
      // let url = 'https://www.baidu.com?age=20&name=llq';
      // let res1 = encodeURI(url);//对空格 不会对: 一般是对整个url编码
      // let res2 = encodeURIComponent(url); //对 ? = / : 都会  一般是对url参数编码
      // console.log(res1);
      // console.log(res2);

      // 浏览器
      //  1先主代码
      //  2微任务
      //  3宏任务
      // 注意：每次执行完一个宏任务 就会立刻去查找执行微任务

      // node事件
      //  1先主代码
      // 2.  process.nextTick()
      //3.    Promise     2 3 都是微任务

      // timer 模块0ms
      // i/o I/O 回调。
      // check模块    setimmediate()
      //close callbacks

      //监听hash路由的改变
      window.onhashchange = (e) => {
        console.log(e.oldURL);
        console.log(e.newURL);
        console.log(location.hash);
      };

      //监听浏览器前进后退
      Window.onpopstate = (e) => {
        console.log(e);
      };

      // const _historyWrap = function (type) {
      //   const orig = history[type];
      //   const e = new Event(type);
      //   return function () {
      //     const rv = orig.apply(this, arguments);
      //     e.arguments = arguments;
      //     window.dispatchEvent(e);
      //     return rv;
      //   };
      // };
      // history.pushState = _historyWrap('pushState');
      // history.replaceState = _historyWrap('replaceState');

      //切换路由
      // history.pushState()
      /*   history.pushState()解释向浏览器历史添加了增加一个记录。
      history.pushState(stateObject, title, url);
      stateObject：状态
title：标题（--几乎没有浏览器支持该参数，但是传一个空字符串会比较安全。）
url：要插入的url 不写的话默认为当前的url */
      // history.replaceState()

      /*********封装localStorage********/
      const setLocalStorage = (key, value) => {
        let data = localStorage.getItem('projectName');
        if (!data) {
          data = {};
        } else {
          data = JSON.parse(data);
        }
        data[key] = value;
        localStorage.setItem('projectName', JSON.stringify(data));
      };
      const getLocalStorage = (key) => {
        let data = localStorage.getItem('projectName');
        if (!data) {
          return {};
        }
        data = JSON.parse(data);
        return data[key] || {};
      };
      // 元素节点1element对应网页的HTML中HTML标签的属性。
      // 文本节点3text代表网页中的标签元素。
      // 元素特性节点2attribute对应网页HTML标签内容。
      // 文档节点4document表示HTML文档，也称为根节点，指向document对象。
      // console.log(Number.parseInt(BigInt(2)));
      // console.table([11, 22, 3]);

      function check(obj) {
        obj.aaa = 777;
      }
      let pp = {
        age: 20,
        name: 'llq',
      };
      check(pp);

      // sort() reverse (): 该方法会改变原来的数组，而不会创建新的数组。

      // console.log(Array.from('123', (item) => item * 2));
      // console.table(pp);
      // let arr1 = [1, 4, 2, 9];
      // console.log([...arr1].sort((a, b) => a - b)); //[9, 2, 4, 1]
      // console.log(arr1);
      // const arr2 = ['a', 'b', 'c', '后盾人'];

      // for (const key of arr2.values()) {
      //   console.log(key);
      // }
      // let lessons = [
      //   { title: '媒体查询响应式布局', category: 'css' },
      //   { title: 'FLEX 弹性盒模型', category: 'css' },
      //   { title: 'MYSQL多表查询随意操作', category: 'mysql' },
      // ];
      // let cssLessons = lessons.filter((item, index, array) => item.category.toLowerCase() == 'css');
      // console.log(cssLessons);

      // let asd = {
      //   age: 20,
      //   name: 'llq',
      // };
      // console.log(asd.hasOwnProperty('age'));
      // console.log(Object.hasOwn(asd, 'age'));

      let hds = {
        title: '后盾人',
        url: 'houdunren.com',
        teacher: {
          name: '向军大叔',
        },
      };
      // console.log(JSON.stringify(hds, null, 4));

      // const promise = new Promise((resolve, reject) => {
      //   resolve('hdcms');
      // })
      //   .then((msg) => {
      //     console.log('resolve');
      //     throw 999;
      //   })
      //   .then((msg) => {
      //     console.log(msg);
      //   })
      //   .catch((err) => {
      //     console.log(45465156);
      //   });

      let numArr = [1, 2, 3];
      numArr.forEach((item) => {
        item = item * 2;
      });
      // console.log(numArr); // 打印结果：[1, 2, 3]

      let objArr = [
        { name: '云牧', age: 20 },
        { name: '许嵩', age: 30 },
      ];

      objArr.forEach((item) => {
        item = {
          name: '邓紫棋',
          age: '29',
        };
      });
      // console.log(JSON.stringify(objArr, null, 4));

      let objArr1 = [
        { name: '云牧', age: 28 },
        { name: '许嵩', age: 30 },
      ];

      // console.time('aaa');
      // objArr1.forEach(async (item, i) => {
      //   setTimeout(() => {
      //     console.log('setTimeout');
      //   }, 1_000 * i);
      //   console.log('邓紫棋');
      // });
      // console.timeEnd('aaa');

      // console.log(JSON.stringify(objArr1, null, 4));
      // console.table(objArr1);
      // console.table([11, 22, 33]);
      // console.table({
      //   title: '423',
      //   cont: '7486456',
      // });
      // window.onbeforeunload = function(e) {
      //   console.log(78978979789789789789);
      //   return '真的要离开吗？';
      // };

      document.onvisibilitychange = (e) => {
        console.log(e.target.visibilityState, e.target.hidden);
      };

      // const hanoi = (line, a, b, c) => {
      //   if (line > 0) {
      //     hanoi(line - 1, a, c, b);
      //     console.log(`${a} -> ${c}`);
      //     hanoi(line - 1, b, a, c);
      //   }
      // };
      // hanoi(3, 'a', 'b', 'c')
      // alert('hello \n world');

      let jsonStudents = [
        { name: 'Dawson', totalScore: '197', Chinese: '100', math: '97' },
        { name: 'HanMeiMei', totalScore: '196', Chinese: '99', math: '97' },
        { name: 'LiLei', totalScore: '185', Chinese: '88', math: '97' },
        { name: 'XiaoMing', totalScore: '196', Chinese: '96', math: '100' },
        { name: 'Jim', totalScore: '196', Chinese: '98', math: '98' },
        { name: 'Joy', totalScore: '198', Chinese: '99', math: '99' },
      ];

      jsonStudents.sort(function (a, b) {
        let value1 = a.totalScore,
          value2 = b.totalScore;
        if (value1 === value2) {
          return b.Chinese - a.Chinese;
        }
        return value2 - value1;
      });
      // console.log(jsonStudents);
      // var arryh = ['A', 'cds', 'esadf', 'As'];
      // arryh.sort();
      // console.log(arryh);

      // console.log((78912).toFixed(2));
      let params = [
        '张三 3 3 3000',
        '李四 3 4 3000',
        '王五 3 3 4000',
        '赵六 4 3 3000',
        '陆奇 4 4 4000',
        '闫八 4 4 3980.99',
      ];

      // 输入样例：
      // 张三 3 3 3000
      // 李四 3 4 3000
      // 王五 3 3 4000
      // 赵六 4 3 3000
      // 陆奇 4 4 4000
      // 闫八 4 4 3980.99

      // 输出样例：
      // 赵六 4 3 3000.00
      // 闫八 4 4 3980.99
      // 陆奇 4 4 4000.00
      // 李四 3 4 3000.00
      // 张三 3 3 3000.00
      // 王五 3 3 4000.00

      //  let params = []
      //   while(line = readline(),strs=readline()){
      //     	params.push((strs)
      //  }

      // 高级sort排序
      const mySorts = (params) => {
        const arrs = [...params];
        const sortArr = [];
        for (let i = 0; i < arrs.length; i++) {
          let tempArr = arrs[i].split(' '),
            name = tempArr[0],
            level = tempArr[1],
            year = tempArr[2],
            money = tempArr[3];
          sortArr.push({ name, level, year, money });
        }
        sortArr.sort((a, b) => {
          let levelA = +a.level,
            levelB = +b.level,
            moneyA = +a.money,
            moneyB = +b.money,
            yearA = +a.year,
            yearB = +b.year;
          if (levelA === levelB) {
            if (moneyA === moneyB) return yearB - yearA;
            return moneyA - moneyB;
          }
          return levelB - levelA;
        });
        for (let i = 0; i < sortArr.length; i++) {
          let { name, level, year, money } = sortArr[i];
          money = (money * 1).toFixed(2);
          const item = `${name} ${level} ${year} ${money}`;
          console.log(item);
        }
      };
      // mySorts(params);

      const nomaToInt = function (s) {
        let map = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
        let sArr = s.split('').reverse();
        return sArr.reduce((res, str, index, arr) => {
          if (index == 0) return map[str];
          let pre = map[arr[index - 1]];
          return (res += map[str] >= pre ? map[str] : pre - map[str] - pre);
        }, 0);
      };

      const noma2Int = function (s) {
        const map = {
          I: 1,
          V: 5,
          X: 10,
          L: 50,
          C: 100,
          D: 500,
          M: 1000,
        };
        let res = 0;
        for (let i = 0; i < s.length; i++) {
          if (map[s[i]] < map[s[i + 1]]) {
            res -= map[s[i]];
          } else {
            res += map[s[i]];
          }
        }
        return res;
      };

      // alert(+'12' > +'9');
      // confirm();

      // 创建自定义事件
      // let myEvent = new CustomEvent('pingan', {
      //   detail: { name: 'wangpingan' },
      // });
      // // 添加适当的事件监听器
      // window.addEventListener('pingan', (e) => {
      //   alert(`pingan事件触发，是 ${e.detail.name} 触发。`);
      // });

      // document.getElementById('leo2').addEventListener('click', function() {
      //   // 派发事件
      //   window.dispatchEvent(pingan2Event);
      // });
      try {
        console.log('try');
        console.log(ry);
      } catch (error) {
        console.warn(error);
        // throw error;
        // throw new Error(error);
        // return error;
      } finally {
        console.log('finally');
      }
      console.log(7897897);
      // document.querySelector('.btn').addEventListener('click', function () {
      //   console.log(this);
      //   this.classList.add('animate__animated', 'animate__bounceOutRight');
      // });
    </script>
  </body>
</html>
